/******************************************************************************
 * Filename : uc_shrm.c
 * Copyright: 
 * Created  : 2010-11-9 by franco.yin
 * Description -
 * 
 ******************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

#include "uc_shrm.h"

int
ucshrm_init(ucshrm_s * pshr, key_t key, int size)
{
	int shmid = 0;

	shmid = shmget(key, size, IPC_CREAT | 0666);
	if (shmid < 0) {
		pshr->shrmid = -1;
		pshr->key = 0;
		pshr->ptr = NULL;
		return ERROR;
	}
	pshr->shrmid = shmid;
	pshr->key = key;
	pshr->ptr = NULL;
	return OK;
}

char *
ucshrm_attach(ucshrm_s * pshr)
{
	if (pshr->shrmid < 0) {
		return NULL;
	}
	pshr->ptr = (char *) shmat(pshr->shrmid, NULL, 0);
	return (pshr->ptr);
}

void
ucshrm_detach(ucshrm_s * pshr)
{
	if (pshr->ptr <= 0) {
		return;
	}
	shmdt(pshr->ptr);
}

void
ucshrm_free(ucshrm_s * pshr)
{
	if ((pshr->ptr <= 0) || (pshr->shrmid < 0)) {
		return;
	}
	shmdt(pshr->ptr);
	shmctl(pshr->shrmid, IPC_RMID, NULL);
	pshr->ptr = NULL;
	pshr->key  = 0;
	pshr->shrmid = -1;
}

char *
ucshrm_hash_creat(int size, char **pTail, ucshrm_create_key pFun, void *p)
{
	int i = 0;
	ucshrm_hash_table_s *pTable = NULL;

	pTable = (ucshrm_hash_table_s *) (*pTail);
	*pTail += sizeof (ucshrm_hash_table_s);

	pTable->pHead = (ucshrm_hash_node_s *) (*pTail);
	*pTail += sizeof (ucshrm_hash_node_s) * size;

	for (i = 0; i < size; i++) {
		uclist_init(&(((pTable->pHead)[i]).list));
	}

	pTable->size = size;
	pTable->pCreat_key = pFun;
	pTable->p = p;
	return (char *) pTable;
}

int
ucshrm_hash_add(ucnode_s * pNode, char *pTable)
{
	int key = 0;
	ucshrm_hash_table_s *table = (ucshrm_hash_table_s *) pTable;
	//ucnode_s *phead = NULL;

	key = (table->pCreat_key) (pNode, table->p);
	if ((key < 0) || (key >= table->size)) {
		uc_err("ucshrm_hash_add key error\n");
		return ERROR;
	}

	//phead = &((table->pHead[key]).list);
	uclist_add_tail(pNode, &((table->pHead[key]).list));
	return OK;
}

static char *
ucshrm_hash_ext_p_char(char **pData, int ext)
{
	char *pTmp = NULL;

	pTmp = *pData;
	pTmp += ext;
	return pTmp;
}

static ucnode_s *
ucshrm_hash_ext_p_list(ucnode_s ** pData, int ext)
{
	return (ucnode_s *) ucshrm_hash_ext_p_char((char **) pData, ext);
}

static ucshrm_hash_node_s *
ucshrm_hash_ext_p_node(ucshrm_hash_node_s ** pData, int ext)
{
	return (ucshrm_hash_node_s *) ucshrm_hash_ext_p_char((char **) pData,
							   ext);
}

static ucshrm_hash_table_s *
ucshrm_hash_ext_p_table(ucshrm_hash_table_s ** pData, int ext)
{
	return (ucshrm_hash_table_s *) ucshrm_hash_ext_p_char((char **) pData,
							    ext);
}

ucnode_s *
ucshrm_hash_walk(char *table, int ext, int key, ucshrm_walk_fun func, void *p)
{
	ucshrm_hash_node_s *head = NULL;
	ucshrm_hash_table_s *pTable = (ucshrm_hash_table_s *) table;

	pTable = ucshrm_hash_ext_p_table(&pTable, ext);
	head = pTable->pHead + key;
	head = ucshrm_hash_ext_p_node(&head, ext);
	if ((key >= 0) && (key < pTable->size)) {
		ucnode_s *pos = NULL;
		ucnode_s *pHead = (ucnode_s *) head;

		pos = ucshrm_hash_ext_p_list(&(pHead->next), ext);
		while (pos != pHead) {
			if (func(pos, ext, p)) {
				return pos;
			}
			pos = ucshrm_hash_ext_p_list(&(pos->next), ext);
		}
	}
	return NULL;
}

#ifdef __cplusplus
}
#endif

